package com.zp.oauth2.gateway.config;

import com.zp.common.base.constant.Atom;
import com.zp.oauth2.gateway.exception.GateWayAccessDeniedHandler;
import com.zp.oauth2.gateway.exception.GateWayUnauthorizedHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.server.resource.web.server.ServerBearerTokenAuthenticationConverter;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.authentication.AuthenticationWebFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

import javax.annotation.Resource;

/**
 *  Security网关配置类
 *
 * @author zp
 */
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
    /**
     * jwt身份验证管理器
     */
    @Resource
    private MyJwtAuthenticationManager myJwtAuthenticationManager;
    /**
     * 鉴权管理器
     */
    @Resource
    private MyJwtAccessManager myJwtAccessManager;

    /**
     * 鉴权失败处理器
     */
    @Resource
    private GateWayAccessDeniedHandler gateWayAccessDeniedHandler;

    /**
     * 认证失败处理器
     */
    @Resource
    private GateWayUnauthorizedHandler gateWayUnauthorizedHandler;

    /**
     * 跨域配置
     *
     */
    @Bean
    public CorsWebFilter corsWebFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        CorsConfiguration corsConfiguration = new CorsConfiguration();
        //1.配置跨域
        //允许哪种请求头跨域
        corsConfiguration.addAllowedHeader("*");
        //允许哪种方法类型跨域 get post delete put
        corsConfiguration.addAllowedMethod("*");
        // 允许哪些请求源跨域
        corsConfiguration.addAllowedOrigin("*");
        // 是否携带cookie跨域
        corsConfiguration.setAllowCredentials(true);

        //允许跨域的路径
        source.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsWebFilter(source);
    }

    /**
     * 网关整合Security配置
     *
     */
    @Bean
    SecurityWebFilterChain webFluxSecurityFilterChain(ServerHttpSecurity http){
        //认证过滤器，放入认证管理器tokenAuthenticationManager
        AuthenticationWebFilter authenticationWebFilter = new AuthenticationWebFilter(myJwtAuthenticationManager);
        authenticationWebFilter.setServerAuthenticationConverter(new ServerBearerTokenAuthenticationConverter());

          http
                .httpBasic().disable()
                .csrf().disable()
                .authorizeExchange()
                //白名单直接放行,这里作为示例放行登录和认证
                .pathMatchers(Atom.EXCLUSION_PATHS).permitAll()
                //其他的请求必须鉴权，使用鉴权管理器
                .anyExchange()
                .access(myJwtAccessManager)
                //鉴权的异常处理，权限不足，token失效
                .and().exceptionHandling()
                .authenticationEntryPoint(gateWayUnauthorizedHandler)
                .accessDeniedHandler(gateWayAccessDeniedHandler)
                .and()
                // 跨域过滤器
                .addFilterAt(corsWebFilter(), SecurityWebFiltersOrder.CORS)
                //token的认证过滤器，用于校验token和认证
                .addFilterAt(authenticationWebFilter, SecurityWebFiltersOrder.AUTHENTICATION);

        return http.build();

    }
}
